package com.comba.nutz.boot.starter.datasource;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * 保证该AOP在@Transactional之前执行
 *
 * @author george
 */
@Aspect
@Order(-10)
@Component
public class DataSourceAspect {

    private static final Logger logger = LoggerFactory.getLogger(DataSourceAspect.class);

    /**
     * @Before("@annotation(ds)") 的意思是：
     * @Before：在方法执行之前进行执行：
     * @annotation(targetDataSource)： 会拦截注解targetDataSource的方法，否则不拦截;
     */
    @Before("@annotation(targetDataSource)")
    public void changeDataSource(JoinPoint point, TargetDataSource targetDataSource) {
        // 获取当前的指定的数据源;
        String type = getDataSourceType(targetDataSource);
        // 如果不在我们注入的所有的数据源范围之内，那么输出警告信息，系统自动使用默认的数据源。
        if (!DataSourceContextHolder.containsDataSource(type)) {
            logger.error("数据源[{}]不存在，使用默认数据源 > {}" + type + point.getSignature());
        } else {
            logger.info("Use DataSource : {" + type + "} > {" + point.getSignature() + "}");
            // 找到的话，那么设置到动态数据源上下文中。
            DataSourceContextHolder.setDataSourceType(type);
        }
    }

    private String getDataSourceType(TargetDataSource targetDataSource) {
        return targetDataSource.value();
    }

    @After("@annotation(targetDataSource)")
    public void restoreDataSource(JoinPoint point, TargetDataSource targetDataSource) {
        String type = getDataSourceType(targetDataSource);
        logger.info("Revert DataSource : {" + type + "} > {" + point.getSignature() + "}");
        // 方法执行完毕之后，销毁当前数据源信息，进行垃圾回收。
        DataSourceContextHolder.clearDataSourceType();
    }
}
